package pow

import (
	"bytes"
	"fmt"
	"math/big"
	"publicChainSystemTest/tools"
	"publicChainSystemTest/transaction"
	"strconv"
)

/**
 *@author:zhengyilong
 *@email:1797344574@qq.com
 *@phone:13479394730
 *@DateTime:2022/4/11 9:54
 **/

const targetBits = 5

type ProofOfwork struct {
	//Timestamp int64
	//Data []byte
	//PrevHash []byte
	Block BlockInterface
	Target *big.Int
}

type BlockInterface interface {
	GetTimestamp() int64
	GetTxs() []transaction.Transaction
	GetPrevHash() []byte
}

func NewProofOfWork(blockInterface BlockInterface)*ProofOfwork  {
	newInt := big.NewInt(1)
	target := newInt.Lsh(newInt, 255-targetBits)
	ofwork := ProofOfwork{
		//Timestamp: timestamp,
		//Data:      data,
		//PrevHash:  prevHash,
		Block: blockInterface,
		Target:    target,
	}
	return &ofwork
}

//返回哈希，随机数
func (pow *ProofOfwork)Run()([]byte,int64) {
	block := pow.Block
	num := big.NewInt(0)
	var nonce int64 = 0

	for {
		timestamp := []byte(strconv.FormatInt(block.GetTimestamp(),10))
		nonceBytes := []byte(strconv.FormatInt(nonce,10))

		txsBytes := []byte{}
		for _, value := range block.GetTxs() {
			serialize, _ := value.Serialize()
			txsBytes = append(txsBytes,serialize...)
		}

		join := bytes.Join([][]byte{timestamp, txsBytes, block.GetPrevHash(), nonceBytes}, []byte{})
		sha256 := tools.Sha256(join)
		num := num.SetBytes(sha256)
		if(num.Cmp(pow.Target) == -1)  {
			return sha256,nonce
		}
		fmt.Printf("正在寻找nonce,当前的nonce为：%d\n",nonce)
		nonce++
	}
}